#include <string.h>
#include "rmff_queue.h"
#include "memory.h"
#include "shin_log.h"
#include "io_util.h"
#include "audio.h"
#include "video.h"

int rmff_queue_init(rmff_queue_t *queue, uint32_t maximum)
{
	if(!maximum)return -1;
	memset(queue, 0, sizeof(rmff_queue_t));
	queue->head = queue->tail = 0;
	queue->capacity = maximum;
	queue->storage = shin_malloc(sizeof(rmff_packet_t*[maximum]));
	return 0;
}

void rmff_queue_free(rmff_queue_t *queue)
{
	uint32_t t = queue->head + 1;
	while(queue->head != t)
	{
		if(queue->storage[t])rmff_release_packet(queue->storage[t]);
		t = (t + 1) % queue->capacity;
	}
	shin_free(queue->storage);
}

rmff_packet_t* rmff_queue_get_packet(rmff_queue_t *queue)
{
	rmff_packet_t *ret;

	while(!queue->num_packets)
	{
		queue->get_tid = sceKernelGetThreadId();
		queue->get_sleep = 1;
		debug_log("get sleep");
		sceKernelSleepThread();
		debug_log("get wakeup");
		queue->get_sleep = 0;
	}
	ret = queue->storage[queue->head];
	queue->head = (queue->head + 1) % queue->capacity;
	if(--queue->num_packets < queue->capacity / 3 && queue->put_sleep)
		sceKernelWakeupThread(queue->put_tid);
	return ret;
}

void rmff_queue_tail_add(rmff_queue_t *queue, rmff_packet_t *pkt)
{
	uint32_t t;
	if(queue->storage[queue->tail])rmff_release_packet(queue->storage[queue->tail]);
	queue->storage[queue->tail] = pkt;
	t = (queue->tail + 1) % queue->capacity;
	queue->num_packets++;
	while(queue->head == t)
	{
		queue->put_tid = sceKernelGetThreadId();
		queue->put_sleep = 1;
//		debug_log("put going to sleep");
		sceKernelSleepThread();
		queue->put_sleep = 0;
	}
	queue->tail = t;
	if(queue->get_sleep && queue->num_packets > queue->capacity / 4)
		sceKernelWakeupThread(queue->get_tid);
}

void rmff_queue_put_packet(rmff_queue_t *queue, rmff_packet_t *packet)
{
	switch(packet->stream->codec)
	{
		case CODEC_RV40:
			rv40_put_packet(queue, packet);
			break;
		case CODEC_AAC:
			aac_put_packet(queue, packet);
			break;
		default:
			rmff_queue_tail_add(queue, packet);
	}
}
